/** 缓存存储映射 */
const cacheMap = new WeakMap<object, Map<string, unknown>>();

/**
 * 缓存装饰器 - 为方法调用结果提供缓存功能
 * @param value 原始方法函数
 * @param ctx 装饰器上下文
 * @returns 包装后的缓存方法或原始函数
 */
export function cached<This extends object, Args extends unknown[], Return>(
  value: (this: This, ...args: Args) => Return,
  ctx: DecoratorContext,
) {
  if (ctx.kind === 'method') {
    return function (this: This, ...args: Args): Return {
      try {
        // 类型安全检查
        if (!isValidInstance(this)) {
          console.warn('缓存装饰器：实例类型无效，直接执行原方法');
          return value.apply(this, args);
        }

        // 获取并判断缓存
        const { value: cache, hasValue } = getCache(this, args);

        if (hasValue) return cache as Return;

        // 如果没有则进行设置并返回新值
        const result = value.apply(this, args);

        setCache(this, args, result);

        return result;
      } catch (err) {
        console.error(`缓存${String(ctx.name)}结果出错:`, err);
        // 异常时仍尝试执行原方法
        return value.apply(this, args);
      }
    };
  }

  // 非 method 类型时返回原始函数
  return value;
}

/**
 * 获取缓存值
 * @param instance 实例对象
 * @param args 方法参数
 * @returns 缓存结果对象，包含是否存在和值
 */
function getCache(
  instance: object,
  args: unknown[],
): { hasValue: boolean; value?: unknown } {
  try {
    if (!isValidInstance(instance)) {
      return { hasValue: false };
    }

    const key = generateCacheKey(args);
    const instanceCache = cacheMap.get(instance);

    if (!instanceCache) {
      return { hasValue: false };
    }

    const hasValue = instanceCache.has(key);
    const value = hasValue ? instanceCache.get(key) : undefined;

    return {
      hasValue,
      value,
    };
  } catch (err) {
    console.error('获取缓存时出错:', err);
    return { hasValue: false };
  }
}

/**
 * 设置缓存值
 * @param instance 实例对象
 * @param args 方法参数
 * @param value 要缓存的值
 */
function setCache(instance: object, args: unknown[], value: unknown): void {
  try {
    if (!isValidInstance(instance)) {
      return;
    }

    const key = generateCacheKey(args);
    let instanceCache = cacheMap.get(instance);

    if (!instanceCache) {
      instanceCache = new Map();
      cacheMap.set(instance, instanceCache);
    }

    instanceCache.set(key, value);
  } catch (err) {
    console.error('设置缓存时出错:', err);
  }
}

/**
 * 生成安全的缓存键
 * @param args 方法参数
 * @returns 缓存键字符串
 */
function generateCacheKey(args: unknown[]): string {
  try {
    // 使用 JSON.stringify 确保键的唯一性
    return JSON.stringify(args);
  } catch (err) {
    // 如果序列化失败，回退到简单拼接（添加分隔符避免冲突）
    console.warn('参数序列化失败，使用简单拼接策略:', err);
    return args.map((arg, index) => `${index}:${String(arg)}`).join('|');
  }
}

/**
 * 验证实例是否有效
 * @param instance 要验证的实例
 * @returns 是否为有效实例
 */
function isValidInstance(instance: unknown): instance is object {
  return instance !== null && typeof instance === 'object';
}
